﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Controls.Primitives;
using HugeFlow.OOB.Behaviors;
using System.ComponentModel;

namespace HugeFlow.OOB.Controls
{
    [TemplatePart(Name = WindowChrome.MinimizeButtonName, Type = typeof(Button))]
    [TemplatePart(Name = WindowChrome.MaximizeButtonName, Type = typeof(ButtonBase))]
    [TemplatePart(Name = WindowChrome.CloseButtonName, Type = typeof(Button))]
    [TemplatePart(Name = WindowChrome.ResizeBottomHandleName, Type = typeof(FrameworkElement))]
    [TemplatePart(Name = WindowChrome.ResizeBottomLeftHandleName, Type = typeof(FrameworkElement))]
    [TemplatePart(Name = WindowChrome.ResizeBottomRightHandleName, Type = typeof(FrameworkElement))]
    [TemplatePart(Name = WindowChrome.ResizeTopHandleName, Type = typeof(FrameworkElement))]
    [TemplatePart(Name = WindowChrome.ResizeTopLeftHandleName, Type = typeof(FrameworkElement))]
    [TemplatePart(Name = WindowChrome.ResizeTopRightHandleName, Type = typeof(FrameworkElement))]
    [TemplatePart(Name = WindowChrome.ResizeLeftHandleName, Type = typeof(FrameworkElement))]
    [TemplatePart(Name = WindowChrome.ResizeRightHandleName, Type = typeof(FrameworkElement))]
    public class WindowChrome : ContentControl
    {
        #region Members

        internal const string MinimizeButtonName = "MinimizeButton";
        internal Button MinimizeButton;

        internal const string MaximizeButtonName = "MaximizeButton";
        internal ButtonBase MaximizeButton;

        internal const string CloseButtonName = "CloseButton";
        internal Button CloseButton;

        internal const string ResizeTopHandleName = "ResizeTopHandle";
        internal FrameworkElement ResizeTopHandle;

        internal const string ResizeTopLeftHandleName = "ResizeTopLeftHandle";
        internal FrameworkElement ResizeTopLeftHandle;

        internal const string ResizeTopRightHandleName = "ResizeTopRightHandle";
        internal FrameworkElement ResizeTopRightHandle;

        internal const string ResizeBottomHandleName = "ResizeBottomHandle";
        internal FrameworkElement ResizeBottomHandle;

        internal const string ResizeBottomLeftHandleName = "ResizeBottomLeftHandle";
        internal FrameworkElement ResizeBottomLeftHandle;

        internal const string ResizeBottomRightHandleName = "ResizeBottomRightHandle";
        internal FrameworkElement ResizeBottomRightHandle;

        internal const string ResizeLeftHandleName = "ResizeLeftHandle";
        internal FrameworkElement ResizeLeftHandle;

        internal const string ResizeRightHandleName = "ResizeRightHandle";
        internal FrameworkElement ResizeRightHandle;

        #region Title

        /// <summary> 
        /// Gets or sets the Title possible Value of the string object.
        /// </summary> 
        [Category("Common Properties"), Description("OOB Application Title")]
        public string Title
        {
            get { return (string)GetValue(TitleProperty); }
            set { SetValue(TitleProperty, value); }
        }

        /// <summary> 
        /// Identifies the Title dependency property.
        /// </summary> 
        public static readonly DependencyProperty TitleProperty =
                    DependencyProperty.Register(
                          "Title",
                          typeof(string),
                          typeof(WindowChrome),
                          new PropertyMetadata("Application Name", OnTitlePropertyChanged));

        /// <summary>
        /// TitleProperty property changed handler. 
        /// </summary>
        /// <param name="d">WindowChrome that changed its Title.</param>
        /// <param name="e">DependencyPropertyChangedEventArgs.</param> 
        private static void OnTitlePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            WindowChrome _WindowChrome = d as WindowChrome;
            if (_WindowChrome != null)
            {
                //TODO: Handle new value. 
            }
        }

        #endregion Title

        #region AllowResize

        /// <summary> 
        /// Gets or sets the AllowResize possible Value of the bool object.
        /// </summary> 
        [Category("Common Properties"), Description("Allow resize window or not")]
        public bool AllowResize
        {
            get { return (bool)GetValue(AllowResizeProperty); }
            set { SetValue(AllowResizeProperty, value); }
        }

        /// <summary> 
        /// Identifies the AllowResize dependency property.
        /// </summary> 
        public static readonly DependencyProperty AllowResizeProperty =
                    DependencyProperty.Register(
                          "AllowResize",
                          typeof(bool),
                          typeof(WindowChrome),
                          new PropertyMetadata(true, OnAllowResizePropertyChanged));

        /// <summary>
        /// AllowResizeProperty property changed handler. 
        /// </summary>
        /// <param name="d">WindowChrome that changed its AllowResize.</param>
        /// <param name="e">DependencyPropertyChangedEventArgs.</param> 
        private static void OnAllowResizePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            WindowChrome _WindowChrome = d as WindowChrome;
            if (_WindowChrome != null)
            {
                _WindowChrome.SetAllowResize((bool)e.NewValue);
            }
        }

        private void SetAllowResize(bool allowResize)
        {
            SetResizeHandleIsHitTestVisible(ResizeTopHandle, allowResize);
            SetResizeHandleIsHitTestVisible(ResizeTopHandle, allowResize);
            SetResizeHandleIsHitTestVisible(ResizeTopLeftHandle, allowResize);
            SetResizeHandleIsHitTestVisible(ResizeTopRightHandle, allowResize);
            SetResizeHandleIsHitTestVisible(ResizeBottomHandle, allowResize);
            SetResizeHandleIsHitTestVisible(ResizeBottomLeftHandle, allowResize);
            SetResizeHandleIsHitTestVisible(ResizeBottomRightHandle, allowResize);
            SetResizeHandleIsHitTestVisible(ResizeLeftHandle, allowResize);
            SetResizeHandleIsHitTestVisible(ResizeRightHandle, allowResize);

            if (MaximizeButton != null)
            {
                if (allowResize == true)
                {
                    MaximizeButton.Visibility = System.Windows.Visibility.Visible;
                }
                else
                {
                    MaximizeButton.Visibility = System.Windows.Visibility.Collapsed;
                }
            }
        }

        private void SetResizeHandleIsHitTestVisible(FrameworkElement resizeHandle, bool isHitTestVisible)
        {
            if (resizeHandle == null)
                return;

            resizeHandle.IsHitTestVisible = isHitTestVisible;
        }

        #endregion AllowResize

        private bool _allowResizeBackuped;

        #endregion Members

        #region Constructors

        /// <summary>
        /// 기본생성자
        /// </summary>
        public WindowChrome()
        {
            this.DefaultStyleKey = typeof(WindowChrome);

            Application.Current.Host.Content.FullScreenChanged += new EventHandler(Content_FullScreenChanged);
        }

        #endregion Constructors

        #region Methods

        /// <summary>
        /// OnApplyTemplate 오버라이드
        /// </summary>
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            // 최소화버튼에 최소화 비헤이비어 붙이기
            MinimizeButton = this.GetTemplateChild(WindowChrome.MinimizeButtonName) as Button;
            if (MinimizeButton != null)
            {
                OOBMinimizeWindowBehavior minimizeBehavior = new OOBMinimizeWindowBehavior();
                minimizeBehavior.Attach(MinimizeButton);
            }

            // 최소화버튼에 최소화 비헤이비어 붙이기
            MaximizeButton = this.GetTemplateChild(WindowChrome.MaximizeButtonName) as ButtonBase;
            if (MaximizeButton != null)
            {
                OOBMaximizeWindowBehavior maximizeBehavior = new OOBMaximizeWindowBehavior();
                maximizeBehavior.Attach(MaximizeButton);
            }

            // 최소화버튼에 최소화 비헤이비어 붙이기
            CloseButton = this.GetTemplateChild(WindowChrome.CloseButtonName) as Button;
            if (CloseButton != null)
            {
                OOBCloseWindowBehavior closeBehavior = new OOBCloseWindowBehavior();
                closeBehavior.Attach(CloseButton);
            }

            // 드래그 지원
            OOBDragMoveWindowBehavior dragBehavior = new OOBDragMoveWindowBehavior();
            dragBehavior.Attach(this);

            // Resize Top
            ResizeTopHandle = this.GetTemplateChild(WindowChrome.ResizeTopHandleName) as FrameworkElement;
            if (ResizeTopHandle != null)
            {
                ResizeTopHandle.Cursor = Cursors.SizeNS;
                OOBDragResizeWindowBehavior resizeBehavior = new OOBDragResizeWindowBehavior() { WindowResizeEdge = WindowResizeEdge.Top };
                resizeBehavior.Attach(ResizeTopHandle);
            }

            // Resize TopLeft
            ResizeTopLeftHandle = this.GetTemplateChild(WindowChrome.ResizeTopLeftHandleName) as FrameworkElement;
            if (ResizeTopLeftHandle != null)
            {
                ResizeTopLeftHandle.Cursor = Cursors.SizeNWSE;
                OOBDragResizeWindowBehavior resizeBehavior = new OOBDragResizeWindowBehavior() { WindowResizeEdge = WindowResizeEdge.TopLeft };
                resizeBehavior.Attach(ResizeTopLeftHandle);
            }

            // Resize TopRight
            ResizeTopRightHandle = this.GetTemplateChild(WindowChrome.ResizeTopRightHandleName) as FrameworkElement;
            if (ResizeTopRightHandle != null)
            {
                ResizeTopRightHandle.Cursor = Cursors.SizeNESW;
                OOBDragResizeWindowBehavior resizeBehavior = new OOBDragResizeWindowBehavior() { WindowResizeEdge = WindowResizeEdge.TopRight };
                resizeBehavior.Attach(ResizeTopRightHandle);
            }

            // Resize Bottom
            ResizeBottomHandle = this.GetTemplateChild(WindowChrome.ResizeBottomHandleName) as FrameworkElement;
            if (ResizeBottomHandle != null)
            {
                ResizeBottomHandle.Cursor = Cursors.SizeNS;
                OOBDragResizeWindowBehavior resizeBehavior = new OOBDragResizeWindowBehavior() { WindowResizeEdge = WindowResizeEdge.Bottom };
                resizeBehavior.Attach(ResizeBottomHandle);
            }
            // Resize BottomLeft
            ResizeBottomLeftHandle = this.GetTemplateChild(WindowChrome.ResizeBottomLeftHandleName) as FrameworkElement;
            if (ResizeBottomLeftHandle != null)
            {
                ResizeBottomLeftHandle.Cursor = Cursors.SizeNESW;
                OOBDragResizeWindowBehavior resizeBehavior = new OOBDragResizeWindowBehavior() { WindowResizeEdge = WindowResizeEdge.BottomLeft };
                resizeBehavior.Attach(ResizeBottomLeftHandle);
            }
            // Resize BottomRight
            ResizeBottomRightHandle = this.GetTemplateChild(WindowChrome.ResizeBottomRightHandleName) as FrameworkElement;
            if (ResizeBottomRightHandle != null)
            {
                ResizeBottomRightHandle.Cursor = Cursors.SizeNWSE;
                OOBDragResizeWindowBehavior resizeBehavior = new OOBDragResizeWindowBehavior() { WindowResizeEdge = WindowResizeEdge.BottomRight };
                resizeBehavior.Attach(ResizeBottomRightHandle);
            }
            // Resize Left
            ResizeLeftHandle = this.GetTemplateChild(WindowChrome.ResizeLeftHandleName) as FrameworkElement;
            if (ResizeLeftHandle != null)
            {
                ResizeLeftHandle.Cursor = Cursors.SizeWE;
                OOBDragResizeWindowBehavior resizeBehavior = new OOBDragResizeWindowBehavior() { WindowResizeEdge = WindowResizeEdge.Left };
                resizeBehavior.Attach(ResizeLeftHandle);
            }

            // Resize Right
            ResizeRightHandle = this.GetTemplateChild(WindowChrome.ResizeRightHandleName) as FrameworkElement;
            if (ResizeRightHandle != null)
            {
                ResizeRightHandle.Cursor = Cursors.SizeWE;
                OOBDragResizeWindowBehavior resizeBehavior = new OOBDragResizeWindowBehavior() { WindowResizeEdge = WindowResizeEdge.Right };
                resizeBehavior.Attach(ResizeRightHandle);
            }

            InitializeProperties();
        }

        /// <summary>
        /// 프로퍼티를 초기화합니다.
        /// </summary>
        private void InitializeProperties()
        {
            if (DesignerProperties.IsInDesignTool == true)
                return;

            SetAllowResize(AllowResize);
        }

        #endregion Methods


        #region EventHandlers

        void Content_FullScreenChanged(object sender, EventArgs e)
        {
            if (Application.Current.Host.Content.IsFullScreen == true)
            {
                _allowResizeBackuped = AllowResize;

                AllowResize = false;
            }
            else
            {
                AllowResize = _allowResizeBackuped;
            }
        }

        #endregion EventHandlers

    }
}
